function [MosMom,tsOut] = InspOffsetMom(statName,OptsGen,ICV,OptPre,d12)
%InspOffsetMom - GNSS time series inspection and manual offset detection
%
%       [MosMom,tsOut] = InspOffsetMom(statName,OptsGen,ICV,OptPre,d12)
%       [MosMom,tsOut] = InspOffsetMom(statName,OptsGen,ICV,d12)
%       [MosMom,tsOut] = InspOffsetMom(statName,OptsGen,ICV)
%       [MosMom,tsOut] = InspOffsetMom(statName,OptsGen)
%
% This function allows the inspection of the time series related to the 
% GNSS station statName, for which the tsData object is already available,
% on the basis of the general option struct variable OptsGen, in order to 
% manually detect possible offsets in one or more of the components encoded 
% by the scalar/vector ICV (see below) in the time span [d12(1), d12(2)].
%
% The input tsData file is searched of the basis of the station name, 
% statName, and information carried by OptsGen in accordance with:
%   filenats = fullfile(OptsGen.dirTs,[statName OptsGen.AddTs '.mat']).
% The upgraded tsData object is the output variable tsOut. The tsData 
% file is automatically upgraded accordingly. 
% If OptsGen is undefined or empty, the .mat file with such a struct
% variable can be interactively managed. 
%
% Options about ICV:
%   - is the vector [0 1 2]: in this case, all the components are managed 
%     (O: East; 1: North; 2: Vertical). These components are shown in three 
%     subplots in this order: East, North, Vertical;
%   - is the vector [0 1]: in this case, only the horizontal components are
%     managed and shown in two subplots in the order East, North;
%   - is the scalar 2: in this case only the vectical component is managed
%     and is shown in a plot;
%   - is undefined or empty. In this case, ICV is OptsGen.components.
% If ICV is different from these cases, ICV = [0 1 2] is used.  
%
% If OptPre is undefined, empty or false, no possible already available data
% about offsests are used, i.e. the offsets search is carried out starting 
% from scratch.
% If OptPre is true, the offsets search starts from the initial MosMom matrix 
% resulting from the used tsData object. 
%
% If the vector d12 is defined and non-empty, the time span [d12(1), d12(2)]
% is considered for these plots. If d12 is undefined ot empty, the lower 
% (upper) time series limit is t(1) (t(end)), where t is the value
% tsDataIn.t. The optional input dates d1 and d2 can be expressed either
% in MATLAB serial date notation or in fractional date notation. 
%
% The user can zoom in the time series with one of these criteria:
%       ZOOM ON 14 DAYS TIME SERIES AROUND A SELECTED TIME
%       ZOOM ON 30 DAYS TIME SERIES AROUND A SELECTED TIME
%       ZOOM ON 6 MONTHS TIME SERIES AROUND A SELECTED TIME
%       ZOOM ON ONE YEAR TIME SERIES AROUND A SELECTED TIME
%       FREE CHOICE OF TIME LIMITS
% As a zoom segment is selected, a figure with this zoom is shown and
% the user can decide if an offset exists along one or more directions.
% The procedure can be repeated. 
% The output matrix Mos shows the detected offsets. If such a matrix is 
% non-empty, the used convention is the CATS one, i.e.  Mos(k,1) is the 
% k-th offset date, always expressed in decimal form, and Mos(k,2) shows 
% the corresponding component(s) according to the "binary notation" 
% (1: detected offset, 0 no detected offset):
%           East   North Vertical  Code
%             1      1      1       7   
%             1      1      0       6
%             1      0      1       5
%             1      0      0       4
%             0      1      1       3
%             0      1      0       2
%             0      0      1       1
%   (clearly, the triad 0-0-0 is excluded)
% If no offsets are selected, Mos = [].
% If tsDataIn is undefined, empty or is not a valid tsData object, the
% name of a MATLAB .mat file is interactively managed. Such a file should  
% carry one or more variables. If a single variable is carried, it must 
% be a tsData object. If two or more variables are carried, one and only 
% one of them must be a 'tsData' object.
%
% See also writeNeuMom, MosMom2MosNeu. 

% G. Teza, 2021, 2022.

font_sz = 14;

if (nargin < 5) || isempty(d12)
    d1 = [];
    d2 = [];
else
    d1 = d12(1);
    d2 = d12(2);
end

if (nargin < 4) || isempty(OptPre)
    OptPre = 0;
end
OptPre = logical(OptPre);

if (nargin < 3) || isempty(ICV)
    ICV = OptsGen.components;
end
if isscalar(ICV) 
    if ICV ~= 2
        ICV = [0 1 2];
    end
elseif length(ICV) == 2
    if sum(ICV == [0 1]) < 2
        ICV = [0 1 2];
    end
elseif length(ICV) == 3
    if sum(ICV == [0 1 2]) < 3
        ICV = [0 1 2];
    end
else
    ICV = [0 1 2];
end

filenats = fullfile(OptsGen.dirTs,[statName OptsGen.AddTs '.mat']);

[ts,IT] = tsDataFileIn(filenats);
if ~IT
    MosMom = [];    
    return
end

t = ts.t;
t1 = t(1);
t2 = t(end);
ed = ts.Ed;
nd = ts.Nd;
vd = ts.Vd;

tenv = [t ed nd vd];

if isempty(d1)
    d1 = t1;
    Id1 = false;
else
    if d1 < 7*10^5
        d1 = frac2serial(d1);
    end
    Id1 = true;
end
if isempty(d2)
    d2 = t2;
    Id2 = false;
else
    if d2 < 7*10^5
        d2 = frac2serial(d2);
    end
    Id2 = true;
end

if Id1 || Id2
    [~,IR1] = min(abs(t-d1));
    [~,IR2] = min(abs(t-d2));
    tenv = tenv(IR1:IR2,:);
    t = tenv(:,1);
    ts.t = t;
    ts.Ed = tenv(:,2); 
    ts.Nd = tenv(:,3);
    ts.Vd = tenv(:,4);
end

if OptPre
    MosMom = MosMomGen(ts);
else
    MosMom = [];   % output matrix initialization
end

Ifig = 0;
while Ifig == 0
    
    strFigGen = sprintf('\nStation %s - time span from %s to % s\n',...
            statName,datestr(d1),datestr(d2));
    fig1 = figure('name',strFigGen,'units','normalized','outerposition',[0 0 1 1]);  
      
    ylimOut = plotEnv(tenv,MosMom,ICV,d1,d2); % ancillary function, see below
    
    pp1 = uicontrol(fig1,'Style', 'popup',...
        'string', {'ZOOM ON 14 DAYS TIME SERIES AROUND A SELECTED TIME',...
        'ZOOM ON 1 MONTH TIME SERIES AROUND A SELECTED TIME',...
        'ZOOM ON 6 MONTHS TIME SERIES AROUND A SELECTED TIME',...
        'ZOOM ON ONE YEAR TIME SERIES AROUND A SELECTED TIME',...
        'FREE CHOICE OF TIME LIMITS',...
        'EXIT'},...
        'FontSize',font_sz,...
        'Units','normalized','Position', [0.05 0.4 0.18 0.1],...
        'Callback', 'uiresume(gcbf)');
    
    txt1 = uicontrol(fig1,'Style','text',...
        'Units','normalized','Position',[0.05 0.5 0.18 0.05],...
        'String','CLICK TO CHOOSE TIME SPAN','FontSize',font_sz);
    
    uiwait(fig1);
    
    vpp1 = pp1.Value;
    
    if vpp1 <= 5
        
        if vpp1 == 1
            [tsi,~] = ginput(1);
            ts1 = tsi-7;
            ts2 = tsi+7;
        elseif vpp1 == 2
            [tsi,~] = ginput(1);
            ts1 = tsi-15;
            ts2 = tsi+15;
        elseif vpp1 == 3
            [tsi,~] = ginput(1);
            ts1 = tsi-92;
            ts2 = tsi+92;
        elseif vpp1 == 4
            [tsi,~] = ginput(1);
            ts1 = tsi-183;
            ts2 = tsi+182;
        else 
            [tsi,~] = ginput(2);
            ts1 = tsi(1);
            ts2 = tsi(2);
        end
        ts1 = max(t(1),ts1);
        ts1 = floor(ts1);
        ts2 = min(t(end),ts2);
        ts2 = ceil(ts2);
        
        strFigSegm = sprintf(...
            '\nStation %s - Selected segment of time series from %s to % s\n',...
            statName,datestr(ts1),datestr(ts2)); 
        disp(strFigSegm);
        
        [~,IS1] = min(abs(t-ts1));
        [~,IS2] = min(abs(t-ts2));
        tenvs = tenv(IS1:IS2,:);
        
        fig2 = figure('name',strFigSegm,'units','normalized',...
            'outerposition',[0.1 0.1 0.9 0.9]);
        plotEnv(tenvs,MosMom,ICV,ts1,ts2,ylimOut);
        pp2 = uicontrol(fig2,'Style', 'popup',...
            'string',... 
            {'OFFSET E-N-V (7)',...
            'OFFSET E-N (6)',...
            'OFFSET E-V (5)',...
            'OFFSET E ONLY (4)',...
            'OFFSET N-V (3)',...
            'OFFSET N ONLY (2)',...
            'OFFSET V ONLY (1)',...
            'DATE ACQUISITION ONLY',...
            'NO OFFSET, NO DATE'},...
            'FontSize',font_sz,...
            'Units','normalized','Position', [0.05 0.45 0.18 0.1],...
            'Callback', 'uiresume(gcbf)');
        uiwait(fig2);
        vpp2 = 8-pp2.Value;     % to have the correct value 
        inddelpp2 = true;       % for delete pp2 
        if vpp2 >= 0
            [tci,~] = ginput(1);
            tci = round(tci);
            if vpp2 > 0
                MosMomMod = [MosMom; tci vpp2];
                delete(pp2);
                inddelpp2 = true;
                xline(MosMomMod(end,1),':r','LineWidth',2);
                pp3 = uicontrol(fig2,'Style', 'popup',...
                    'String',... 
                    {'ACCEPT THE SELECTED OFFSET',...
                    'CANCEL'},...
                    'FontSize',font_sz,...
                    'Units','normalized','Position', [0.05 0.45 0.18 0.1],...
                    'Callback', 'uiresume(gcbf)');
                uiwait(fig2);
                vpp3 = pp3.Value;
                if vpp3 == 1
                    MosMom = MosMomMod;
                end
                delete(pp3);
            else
                sBox = sprintf(...
                    'SELECTED DATE:\nString: %s\nSerial: %d\nFraction: %4.4f\nMJD: %d',...
                    datestr(tci),tci,serial2frac(tci),serial2MJD(tci));
                msgbox(sBox,statName);
            end
        end
        
        if inddelpp2
            delete(pp2);
        end
        close(fig2);
        
        
    else
        
        Ifig = 1;  % end of the selection process
    
    end
    
    close(fig1);
    
end

delete(pp1); delete(txt1);

% Final date conversion:
if ~isempty(MosMom)
    tfrac = serial2MJD(MosMom(:,1));  % MJD date form
    MosMom(:,1) = tfrac;
end

% Output file(s) management
% preliminary step: change MosMom -> MosNeu

MosNeu = MosMom2MosNeu(MosMom);

% Ouput file generation:
[~,~,tsOut]  = writeNeuMom(...
    fullfile(OptsGen.dirObs,[statName OptsGen.AddObs]),ICV,ts,MosNeu);

ts = tsOut;
save(filenats,'ts');

%% Ancillary functions 

function ylimOut = plotEnv(tenv,MosMom,ICV,dl1,dl2,ylimIn)
% Plot  of tenv time series on subplots, including possible vertical offset
% lines. 
% If ylimIn is defined and non-empty, ylimIn(:,k) is the y limit of the 
% k-th channel plot (k-th subplot).
% The output ylimOut(:,k) is the y limit of k-th subplot.
if nargin < 6
    ylimIn = [];
end
nch = numel(ICV);
ylimOut = zeros(nch,2);
if nch > 1
    %
    subplot(nch,1,1); 
    plot(tenv(:,1),tenv(:,2),'.k'); 
    if ~isempty(MosMom)
        I = ismember(MosMom(:,2),4:7);
        if sum(I) > 0
            xline(MosMom(I,1),':k','LineWidth',2);
        end
    end
    datetick('x',28); grid on; 
    ylabel('\itEast \rm(m)');
    xlim([dl1 dl2]);
    if ~isempty(ylimIn)
        ylim(ylimIn(1,:));
    end
    vax1 = axis;
    ylimOut(1,:) = vax1(3:4);
    %
    subplot(nch,1,2); 
    plot(tenv(:,1),tenv(:,3),'.b'); 
    if ~isempty(MosMom)
        I = ismember(MosMom(:,2),[2 3 6 7]);
        if sum(I) > 0
            xline(MosMom(I,1),':b','LineWidth',2);
        end
    end
    datetick('x',28); grid on; 
    ylabel('\itNorth \rm(m)');
    xlim([dl1 dl2]);
    if ~isempty(ylimIn)
        ylim(ylimIn(2,:));
    end
    vax2 = axis;
    ylimOut(2,:) = vax2(3:4);
    %
end
if (nch == 1)||(nch == 3)
    if nch == 3
        subplot(nch,1,3);
    end
    plot(tenv(:,1),tenv(:,4),'.r');
    if ~isempty(MosMom)
        I = ismember(MosMom(:,2),[1 3 5 7]);
        if sum(I) > 0
            xline(MosMom(I,1),':r','LineWidth',2);
        end
    end
    datetick('x',28); grid on; 
    ylabel('\itVertical \rm(m)');
    xlim([dl1 dl2]);
    if ~isempty(ylimIn)
        ylim(ylimIn(3,:));
    end
    vax3 = axis;
    ylimOut(3,:) = vax3(3:4);
end